use super::{basis::Basis, vector3::Vec3};

#[derive(Debug, Clone, PartialEq, Copy, Default)]
pub struct Transform3D {
    pub basis: Basis,
    pub origin: Vec3,
}

impl Transform3D {
    pub fn translate_local(&mut self, x: f32, y: f32, z: f32) {
        self.translate_local_with_vec(&Vec3::new(x, y, z));
    }

    pub fn translate_local_with_vec(&mut self, translation: &Vec3) {
        for i in 0..3 {
            self.origin[i] += self.basis[i].dot(translation)
        }
    }

    pub fn scale(&mut self, scale: &Vec3) {
        self.basis.scale(scale);
        self.origin = self.origin * (*scale);
    }

    pub fn to_col_array(&self) -> [f32; 16] {
        let mut mat = [0.0; 16];
        mat[0] = self.basis[0][0];
        mat[1] = self.basis[1][0];
        mat[2] = self.basis[2][0];
        mat[3] = 0.0;
        mat[4] = self.basis[0][1];
        mat[5] = self.basis[1][1];
        mat[6] = self.basis[2][1];
        mat[7] = 0.0;
        mat[8] = self.basis[0][2];
        mat[9] = self.basis[1][2];
        mat[10] = self.basis[2][2];
        mat[11] = 0.0;
        mat[12] = self.origin.x;
        mat[13] = self.origin.y;
        mat[14] = self.origin.z;
        mat[15] = 1.0;

        mat
    }

    pub fn from_row_slice(raw: &[f32; 16]) -> Self {
        let mut this = Self::default();
        this.basis[0][0] = raw[0];
        this.basis[1][0] = raw[1];
        this.basis[2][0] = raw[2];

        this.basis[0][1] = raw[4];
        this.basis[1][1] = raw[5];
        this.basis[2][1] = raw[6];

        this.basis[0][2] = raw[8];
        this.basis[1][2] = raw[9];
        this.basis[2][2] = raw[10];

        this.origin.x = raw[12];
        this.origin.y = raw[13];
        this.origin.z = raw[14];
        this
    }
}
